package com.glsc.ngateway.opmanage.service.deposit;

import com.glsc.ngateway.common.api.common.utils.DateUtil;
import com.glsc.ngateway.common.api.common.utils.PageUtil;
import com.glsc.ngateway.common.base.domain.mysql.opmanagemain.deposit.*;
import com.glsc.ngateway.common.base.repo.mysql.opmanagemain.deposit.DepositoryDayTrialRepository;
import com.glsc.ngateway.opmanage.dto.DepositoryDayProfitExcelDto;
import com.glsc.ngateway.opmanage.dto.DepositoryDayTrialExcelDto;
import com.glsc.ngateway.opmanage.utils.SpecificationUtil;
import com.glsc.ngateway.opmanage.utils.report.ReportFileConfigEnum;
import com.glsc.ngateway.opmanage.utils.report.ReportFileUtil;
import com.glsc.ngateway.opmanage.utils.report.ReportUploadContext;
import org.apache.commons.lang.StringUtils;
import org.springframework.data.domain.*;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.io.IOException;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;

@Service
public class DepositoryDayTrialService {


    @Resource
    private DepositoryDayTrialRepository depositoryDayTrialRepository;

    @Resource
    private DepositoryBankService bankService;

    @Resource
    private DepositoryBaseDataQuarterService baseDataQuarterService;

    @Resource
    private DepositorySpecialAccountService accountService;

    /**
     * 分页查找
     *
     * @param pageNo
     * @param pageSize
     * @param param
     * @return
     */
    public Page<DepositoryDayTrial> page(int pageNo, int pageSize, Map<String, Object> param) {
        Sort.Direction direction = Sort.Direction.DESC;
        String sort = "createTime";

        pageNo = PageUtil.initPageNo(pageNo);
        pageSize = PageUtil.initPageSize(pageSize);

        Pageable pageable = PageRequest.of(pageNo - 1, pageSize, direction, sort);
        Page<DepositoryDayTrial> page = depositoryDayTrialRepository.findAll(SpecificationUtil.buildSpecification(param, DepositoryDayTrial.class), pageable);

        return page;
    }

    /**
     * 本日数据合计
     *
     * @return
     */
    public DepositoryDayTrial thisDayData() {
        DepositoryDayTrial trial = new DepositoryDayTrial();
        trial.setEffectDate(DateUtil.getNowDateString());
        List<DepositoryDayTrial> trialList = depositoryDayTrialRepository.findAll(Example.of(trial));

        DepositoryDayTrial res = DepositoryDayTrial.builder().bankBalance(BigDecimal.ZERO).counterBalance(BigDecimal.ZERO)
                .interest(BigDecimal.ZERO).depositFloor(BigDecimal.ZERO).adjustTrial(BigDecimal.ZERO)
                .handAdjust(BigDecimal.ZERO).sumAdjust(BigDecimal.ZERO).trialInterestChange(BigDecimal.ZERO).build();

        DepositorySpecialAccount account = accountService.findByTypeAndDate("1", DateUtil.getNowDateString());
        if (Objects.nonNull(account) && Objects.nonNull(account.getAccountValue())) {
            res.setAccountValue(account.getAccountValue());
        }

        if (CollectionUtils.isEmpty(trialList)) {
            return res;
        }
        for (DepositoryDayTrial item : trialList) {
            if (Objects.nonNull(item.getBankBalance())) {
                res.setBankBalance(res.getBankBalance().add(item.getBankBalance()));
            }
            if (Objects.nonNull(item.getCounterBalance())) {
                res.setCounterBalance(res.getCounterBalance().add(item.getCounterBalance()));
            }
            if (Objects.nonNull(item.getInterest())) {
                res.setInterest(res.getInterest().add(item.getInterest()));
            }
            if (Objects.nonNull(item.getDepositFloor())) {
                res.setDepositFloor(res.getDepositFloor().add(item.getDepositFloor()));
            }
            if (Objects.nonNull(item.getAdjustTrial())) {
                res.setAdjustTrial(res.getAdjustTrial().add(item.getAdjustTrial()));
            }
            if (Objects.nonNull(item.getHandAdjust())) {
                res.setHandAdjust(res.getHandAdjust().add(item.getHandAdjust()));
            }
            if (Objects.nonNull(item.getSumAdjust())) {
                res.setSumAdjust(res.getSumAdjust().add(item.getSumAdjust()));
            }
            if (Objects.nonNull(item.getTrialInterestChange())) {
                res.setTrialInterestChange(res.getTrialInterestChange().add(item.getTrialInterestChange()));
            }
        }

        return res;
    }

    /**
     * 根据id查找
     *
     * @param id
     * @return
     */
    public DepositoryDayTrial findById(Integer id) {
        Optional<DepositoryDayTrial> optional = depositoryDayTrialRepository.findById(id);
        if (optional.isPresent()) {
            return optional.get();
        }
        return null;
    }

    /**
     * 保存
     *
     * @param obj
     * @return
     */
    public DepositoryDayTrial save(DepositoryDayTrial obj) {
        if (Objects.isNull(obj.getBankId())) {
            if (StringUtils.isNotBlank(obj.getBankName())) {
                DepositoryBank bank = bankService.findByName(obj.getBankName());
                if (Objects.nonNull(bank)) {
                    obj.setBankId(bank.getId());
                }
            }
        }

        if (Objects.nonNull(obj.getBankId())) {
            DepositoryBank bank = bankService.findById(obj.getBankId());
            obj.setBankName(bank.getBankName());
            //设置生效日期
            obj.setEffectDate(DateUtil.getNowDateString());
            //设置利率
            obj.setInterestRate(bank.getInterestRate());

            //计算当日利息 利率x银行余额/360
            obj.setInterest(bank.getInterestRate().multiply(obj.getBankBalance()).divide(BigDecimal.valueOf(36000), 2, RoundingMode.HALF_UP).setScale(2, RoundingMode.HALF_UP));
            //调整试算

            //最低存放取季度数据中的“拟定存放(手工调整后)”值
            DepositoryBaseDataQuarter baseData = baseDataQuarterService.findNewOneBaseData(obj.getBankId());
            if (Objects.nonNull(baseData)) {
                obj.setDepositFloor(baseData.getIntendedDepositHand());
                obj.setAdjustTrial(obj.getDepositFloor().subtract(obj.getBankBalance()));
                obj.setSumAdjust(obj.getAdjustTrial());
                obj.setTrialInterestChange(((obj.getAdjustTrial()).multiply(obj.getInterestRate()).divide(BigDecimal.valueOf(36000), 2, RoundingMode.HALF_UP)));
                obj.setSumAdjust(obj.getAdjustTrial());
                if (Objects.nonNull(obj.getHandAdjust())) {
                    obj.setTrialInterestChange(((obj.getAdjustTrial().add(obj.getHandAdjust())).multiply(obj.getInterestRate()).divide(BigDecimal.valueOf(36000), 2, RoundingMode.HALF_UP)));
                    obj.setSumAdjust(obj.getAdjustTrial().add(obj.getHandAdjust()));
                }
            }


            obj.setDeleted("N");
        }

        return depositoryDayTrialRepository.save(obj);
    }

    /**
     * 根据id删除
     *
     * @param id
     */
    public void delete(Integer id) {
        depositoryDayTrialRepository.deleteById(id);
    }


    @Transactional
    public ReportUploadContext<DepositoryDayTrialExcelDto, String> important(MultipartFile file) throws IOException {
        ReportUploadContext<DepositoryDayTrialExcelDto, String> context = ReportUploadContext.<DepositoryDayTrialExcelDto, String>builder().config(ReportFileConfigEnum.DEPOSITORY_DAY_TRIAL).file(file).build();

        ReportFileUtil.readSingleExcel(context);
        Assert.notEmpty(context.getReadRes(), "上传内容不可为空");


        List<DepositoryDayTrialExcelDto> readResList = context.getReadRes();
        if (CollectionUtils.isEmpty(readResList)) {
            return context;
        }

        for (DepositoryDayTrialExcelDto dto : readResList) {
            DepositoryDayTrial trial = DepositoryDayTrial.builder().bankName(dto.getBankName()).counterBalance(dto.getCounterBalance()).bankBalance(dto.getBankBalance())
                    .depositFloor(dto.getDepositFloor()).handAdjust(dto.getHandAdjust()).adjustTrial(dto.getAdjustTrial()).purchaseDay(dto.getPurchaseDay())
                    .withdrawalDay(dto.getWithdrawalDay()).afterDayExtract(dto.getAfterDayExtract()).build();
            DepositoryBank bank = bankService.findByName(dto.getBankName());
            if (Objects.nonNull(bank)) {
                trial.setBankId(bank.getId());
            }
            save(trial);
        }


        return context;
    }


    /**
     * 根据id批量删除
     *
     * @param ids
     */
    public void deleteByIdList(List<Integer> ids) {
        depositoryDayTrialRepository.deleteAllById(ids);
    }

}
